package gamecomponents.character;
import gamecomponents.levelcomponents.Stage;
import gamecomponents.levelcomponents.stagelements.Block;
import gamecomponents.levelcomponents.stagelements.buildingmats.ExtendedEntity;
import gamecomponents.levelcomponents.stagelements.buildingmats.Key;
import gamecomponents.levelcomponents.stagemanager.StageBuilder;
import gamecomponents.navigation.Direction;
import gamecomponents.navigation.Location;
import gamecomponents.skeletontesthelper.Assistant;
import gamecomponents.skeletontesthelper.Interaction;
import gamecomponents.skeletontesthelper.Parameter;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Akos
 * @version 1.0
 * @created 14-márc.-2012 16:36:14
 */
public class Player {

	/**
	 * A megszerzett kulcsok referenciai
	 */
	private Set<Key> collectedKeys;
	private static final int HEIGHT = 100;
	private static final int WIDTH = 50;
	/**
	 * helyzete a figurának
	 */
	private Location loc;
	private static final int MAX_JUMPHEIGHT = 400;



	public void finalize() throws Throwable {

	}

	public Player(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CRT,this,"Player",param);
	}

	public int getHeight(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"getHeight",param);
            return HEIGHT;
	}

	/**
	 * get
	 */
	public Location getLastKeysLocation(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"getLastKeyLocation",param);
            Iterator it = collectedKeys.iterator();
            while(it.hasNext()){};
            Location last = (Location)it.next();
            Parameter param2[]=new Parameter[1];
            param2[0]=new Parameter(last);
            Assistant.write(Interaction.RET,this,"getLastKeysLocation",param2);
            return last;
	}

	/**
	 * Location lekérdezés.
	 */
	public Location getLocation(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"getLocation",param);
            Parameter param2[]=new Parameter[1];
            param2[0]=new Parameter(loc);
            Assistant.write(Interaction.RET,this,"getLocation",param2);
            return loc;
	}

	public int getWidth(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"getWidth",param);
            Parameter param2[]=new Parameter[1];
            param2[0]=new Parameter(WIDTH);
            Assistant.write(Interaction.RET,this,"getWidth",param2);
            return WIDTH;
	}

	/**
	 * 
	 * @param nextLoc
	 */
	public boolean moveToThisLocation(Location nextLoc){
            Parameter param0[]=new Parameter[1];
            param0[0]=new Parameter(nextLoc);
            Assistant.write(Interaction.CALL,this,"moveToThisLocation",param0);
            /*
             * Lekérjük az aktuális blokkot és ellenőrizzük, hogy ez
             * azonos-e azzal a blokkal, ami az új location-ban van
             */
            Block activeBlock = loc.getBlock();
            Block nextBlock = nextLoc.getBlock();
            if(activeBlock==nextBlock){
                /*
                 * Ha maradunk az eredeti blokkon, akkor ellenőrizzük, hogy
                 * van-e ott ExtendedEntity, vagyis valami tárgy.
                 */
                ExtendedEntity eE = activeBlock.getExtendedEntityAtThisLocation(nextLoc);
                if(eE!=null){
                    /*
                     * Ha valamilyen tárgyba ütköztünk, ellenőrizzük, hogy
                     * ráléphetünk-e.
                     */
                    if(eE.canIGo()){
                        /*
                         * Ha ráléphetünk, elindítjuk a tárgy speciális akcióját
                         * (PL.: kulcs-ot felvesszük), beállítjuk az új
                         * Location-t és igazzal térünk vissza (sikeres mozgás)
                         */
                        eE.action(this);
                        this.setLocation(nextLoc);
                        Parameter param2[]=new Parameter[1];
                        param2[0]=new Parameter("IsSuccesfull",true);
                        Assistant.write(Interaction.RET,this,"moveToThisLocation",param2);
                        return true;
                    }
                    /*
                     * Ha nem léphetünk oda, mert fal van ott, akkor hamissal
                     * térünk vissza, nem módosítjuk a locationt
                     * (sikertelen mozgás)
                     */
                    Parameter param3[]=new Parameter[1];
                    param3[0]=new Parameter("IsSuccesfull",false);
                    Assistant.write(Interaction.RET,this,"moveToThisLocation",param3);
                    return false;
                }
                /*
                 * Ha csak levegőbe ütköztünk, odalépünk és igazzal térünk
                 * vissza (sikeres mozgás)
                 */
                else{
                    this.setLocation(nextLoc);
                    Parameter param4[]=new Parameter[1];
                    param4[0]=new Parameter("IsSuccesfull",true);
                    Assistant.write(Interaction.RET,this,"moveToThisLocation",param4);
                    return true;
                }
            }
            /*
             * Ha másik blokkra szeretnénk mozgatni a figurát
             * (vagyis nem egyezett meg a két blokk), akkor ellenőrízzük, hogy
             * illeszkedik-e a két blokk.
             */
            else{
                Direction dir = activeBlock.getDirectionOfThisNeighbour(nextBlock);
                /*
                 * Ha illeszkedik a két blokk, akkor átlépünk, igazzal vissza-
                 * térünk. (sikeres mozgás)
                 */
                if(activeBlock.isMatches(dir)){
                    this.setLocation(nextLoc);
                    Parameter param5[]=new Parameter[1];
                    param5[0]=new Parameter("IsSuccesfull",true);
                    Assistant.write(Interaction.RET,this,"moveToThisLocation",param5);
                    return true;
                }
                /*
                 * Ha nem illeszkedik egymásra a két blokk, ellenőrizni kell,
                 * hogy esetleg nem a pálya alján van-e a figura, vagyis nem
                 * zuhan-e le a "semmibe". Ha igen, a játékos meghal. Erről
                 * értesíti a pályát (Stage)
                 */
                else{
                    if(dir==Direction.DOWN){
                        Stage currentStage = StageBuilder.getInstance().getCurrentStage();
                        currentStage.playerDead(this);
                    }
                }
            }
            Parameter param6[]=new Parameter[1];
            param6[0]=new Parameter("IsSuccesfull",false);
            Assistant.write(Interaction.RET,this,"moveToThisLocation",param6);
            return false;
	}

	public boolean canIFall(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"canIFall",param);
            /*
             * Ellenőrizzük, hogy a figura alatt lévő koordinátán van-e tárgy,
             * és ha igen, akkor ráléphet-e.
             * Ha van, akkor megkérdezzük, hogy oda léphet-e és eszerint 
             * visszatérünk, ellenben igazzal térünk vissza, mivel ha nincs
             * tárgy, akkor levegő van, oda pedig mehet a figura, vagyis
             * eshet.
             */
            Block activeBlock = loc.getBlock();
            Location l = new Location();
            l.setBlock(activeBlock);
            l.setCoordinate(loc.getCoordinate());
            l.getCoordinate().setY(l.getCoordinate().getY()-1);
            ExtendedEntity eE = activeBlock.getExtendedEntityAtThisLocation(l);
            if(eE!=null){
                boolean b = eE.canIGo();
                Parameter param2[]=new Parameter[1];
                param2[0]=new Parameter("CanIFall",b);
                Assistant.write(Interaction.RET,this,"moveToThisLocation",param2);
                return b;
            }
            Parameter param3[]=new Parameter[1];
            param3[0]=new Parameter("canIFall",true);
            Assistant.write(Interaction.RET,this,"canIFall",param3);
            return true;
	}

	/**
	 * 
	 * @param _loc
	 */
	private void setLocation(Location _loc){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(loc);
            Assistant.write(Interaction.CALL,this,"setLocation",param);
            loc = _loc;
	}

	/**
	 * 
	 * @param key
	 */
	public void addKey(Key key){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(key);
            Assistant.write(Interaction.CALL,this,"addKey",param);
            collectedKeys.add(key);
	}

	public int getCollectedkeysNumber(){
            Parameter param[]=new Parameter[1];
            param[0]=new Parameter(null);
            Assistant.write(Interaction.CALL,this,"getCollectedKeysNumber",param);
            int number = collectedKeys.size();
            Parameter param2[]=new Parameter[1];
            param2[0]=new Parameter("NumerOfKeys",number);
            Assistant.write(Interaction.RET,this,"moveToThisLocation",param2);
            return number;
	}

}